    <template>
  <view class="container">
    <!-- 顶部导航 -->
    <view class="header">
      <view class="back-btn" @click="goBack">
        <uni-icons type="left" size="20" color="#fff"></uni-icons>
      </view>
      <text class="header-title">帖子详情</text>
      <view class="header-right" @click="openMore">
        <uni-icons type="more-filled" size="20" color="#fff"></uni-icons>
      </view>
    </view>

    <scroll-view
      scroll-y
      class="content"
      :lower-threshold="60"
      @scrolltolower="onScrollToLower"
      :refresher-enabled="true"
      :refresher-triggered="refreshing"
      @refresherrefresh="onRefresherRefresh"
    >
      <!-- 帖子内容 -->
      <view class="post-detail">
        <!-- 用户信息 -->
        <view class="user-info">
          <image class="avatar" :src="postDetail.avatar || defaultAvatar" mode="aspectFill" @click.stop="onClickPostAvatar" @tap.stop="onClickPostAvatar"></image>
          <view class="user-content">
            <view class="user-name">{{ postDetail.username }}</view>
            <view class="post-time">{{ postDetail.time }}</view>
          </view>
          <view class="follow-btn" :class="{ followed: postDetail.isFollowed }" @click="toggleFollow">
            <text>{{ postDetail.isFollowed ? '已关注' : '关注' }}</text>
          </view>
        </view>

        <!-- 帖子标题和内容 -->
        <view class="post-content">
          <text class="post-title" v-if="postDetail.title">{{ postDetail.title }}</text>
          <!-- 元信息：时间、浏览量、标签入口 -->
          <view class="post-meta" v-if="postDetail.time || postDetail.viewCount || (postDetail.tags && postDetail.tags.length)">
            <view class="meta-item" v-if="postDetail.time">
              <uni-icons type="calendar" size="14" color="#999"></uni-icons>
              <text>{{ postDetail.time }}</text>
            </view>
            <view class="meta-item" v-if="postDetail.viewCount">
              <uni-icons type="eye" size="14" color="#999"></uni-icons>
              <text>{{ postDetail.viewCount }}</text>
            </view>
            <view class="meta-item ended" v-if="postDetail.isEnded || postDetail.statusText === '已结束'">
              <uni-icons type="checkbox-filled" size="14" color="#2ecc71"></uni-icons>
              <text>已结束</text>
            </view>
            <view class="meta-tags" v-if="postDetail.tags && postDetail.tags.length">
              <text class="meta-tag" v-for="t in postDetail.tags" :key="t">#{{ t }}</text>
            </view>
          </view>

          <text class="post-text">{{ postDetail.content }}</text>
          
          <!-- 帖子图片（QQ 朋友圈风格：1大图/2两列/3+三宫格） -->
          <view 
            class="post-images"
            v-if="postDetail.images && postDetail.images.length > 0"
            :class="{
              one: postDetail.images.length === 1,
              two: postDetail.images.length === 2,
              grid: postDetail.images.length >= 3
            }"
          >
            <view
              class="image-item"
              v-for="(img, index) in postDetail.images.slice(0, 9)"
              :key="index"
              @click="previewImage(img, postDetail.images)"
            >
              <image :src="img" mode="aspectFill" />
              <view class="more-mask" v-if="index === 8 && postDetail.images.length > 9">
                <text>+{{ postDetail.images.length - 9 }}</text>
              </view>
            </view>
          </view>
        </view>
        
        <!-- 病症信息块 -->
        <view
          class="medical-info"
          v-if="postDetail.deptName || postDetail.diseaseName || postDetail.diseaseDetail || postDetail.treatmentProcess || postDetail.hospitalName"
        >
          <view class="info-row" v-if="postDetail.deptName">
            <text class="label">科室</text>
            <text class="value">{{ postDetail.deptName }}</text>
          </view>
          <view class="info-row" v-if="postDetail.diseaseName">
            <text class="label">病症</text>
            <text class="value">{{ postDetail.diseaseName }}</text>
          </view>
          <view class="info-block" v-if="postDetail.diseaseDetail">
            <text class="label">病症详情</text>
            <text class="value block">{{ postDetail.diseaseDetail }}</text>
          </view>
          <view class="info-block" v-if="postDetail.treatmentProcess">
            <text class="label">治疗经历</text>
            <text class="value block">{{ postDetail.treatmentProcess }}</text>
          </view>
          <view class="info-row" v-if="postDetail.hospitalName">
            <text class="label">就诊医院</text>
            <text class="value">{{ postDetail.hospitalName }}</text>
          </view>
        </view>

        <!-- 帖子标签 -->
        <view class="post-tags" v-if="postDetail.tags && postDetail.tags.length > 0">
          <text class="tag" v-for="tag in postDetail.tags" :key="tag">#{{ tag }}</text>
        </view>

        <!-- 帖子状态徽章：进行中/已结束 -->
        <view class="post-status-badge">
          <text
            class="status-chip"
            :class="{ ended: (postDetail && (postDetail.isEnded || postDetail.statusText === '已结束')) }"
          >
            {{ (postDetail && (postDetail.isEnded || postDetail.statusText === '已结束')) ? '已结束' : '进行中' }}
          </text>
        </view>

        <!-- 互动数据 -->
        <view class="post-stats">
          <view class="stat-item" @click="toggleLike">
            <uni-icons :type="postDetail.isLiked ? 'heart-filled' : 'heart'" 
                      :color="postDetail.isLiked ? '#ff6b6b' : '#999'" size="16"></uni-icons>
            <text :class="{ liked: postDetail.isLiked }">{{ postDetail.likes }}</text>
          </view>
          <view class="stat-item" @click="openComments">
            <uni-icons type="chat" color="#999" size="16"></uni-icons>
            <text>{{ commentTotalCount }}</text>
          </view>
          <view class="stat-item" @click="toggleCollect">
            <uni-icons :type="postDetail.isCollected ? 'star-filled' : 'star'" 
                      :color="postDetail.isCollected ? '#ffd700' : '#999'" size="16"></uni-icons>
            <text :class="{ collected: postDetail.isCollected }">{{ postDetail.collects }}</text>
          </view>
        </view>
      </view>

      <!-- 评论区域 -->
      <view class="comments-section">
        <view class="comments-header">
          <text class="comments-title">评论 ({{ commentTotalCount }})</text>
        </view>
        
        <!-- 评论列表 -->
        <view class="comments-list">
          <view class="comment-item" v-for="comment in comments" :key="comment.id">
            <!-- 顶部右上角固定的采纳按钮/标记，更显眼，便于联调点击 -->
            <view v-if="comment.isAdopted" class="adopt-badge-fixed">
              <uni-icons type="checkbox-filled" color="#2ecc71" size="14"></uni-icons>
              <text style="margin-left:6rpx">已采纳</text>
            </view>
            <view v-else-if="canAdopt(comment)" class="adopt-btn-fixed" :class="{ disabled: adoptLoadingId===comment.id }" @click.stop="onClickAdopt(comment)">
              <uni-icons type="checkbox" color="#2d8cf0" size="14"></uni-icons>
              <text style="margin-left:6rpx">{{ adoptLoadingId===comment.id ? '采纳中...' : '采纳' }}</text>
            </view>
            <image class="comment-avatar" :src="comment.avatar || defaultAvatar" mode="aspectFill" @click.stop="onClickCommentAvatar(comment)" @tap.stop="onClickCommentAvatar(comment)"></image>
            <view class="comment-content">
              <view class="comment-header">
                <text class="comment-username">{{ comment.username }}</text>
                <view class="comment-right">
                  <text class="comment-time">{{ comment.time }}</text>
                </view>
              </view>
              <text class="comment-text">{{ comment.content }}</text>
              
              <!-- 回复列表 -->
              <view class="replies" v-if="comment.replies && comment.replies.length > 0">
                <view class="reply-item" v-for="reply in comment.replies" :key="reply.id">
                  <text class="reply-username">{{ reply.username }}</text>
                  <text class="reply-text">: {{ reply.content }}</text>
                  <text class="reply-time">{{ reply.time }}</text>
                </view>
              </view>
              
              <view class="comment-actions">
                <view class="action-btn" @click="toggleCommentLike(comment)">
                  <uni-icons :type="comment.isLiked ? 'heart-filled' : 'heart'" 
                            :color="comment.isLiked ? '#ff6b6b' : '#999'" size="14"></uni-icons>
                  <text :class="{ liked: comment.isLiked }">{{ comment.likes }}</text>
                </view>
                <view class="action-btn" @click="replyToComment(comment)">
                  <uni-icons type="chat" color="#999" size="14"></uni-icons>
                  <text>回复</text>
                </view>
              </view>
            </view>
          </view>
        </view>
        <!-- 加载更多/没有更多 提示 -->
        <view class="load-more" v-if="loadingComments">加载中...</view>
        <view class="load-more no-more" v-else-if="!hasMoreComments && comments.length > 0">没有更多了</view>
      </view>
    </scroll-view>

    <!-- 底部评论输入框 -->
    <view class="comment-input-section">
      <view class="input-container">
        <input 
          class="comment-input" 
          v-model="newComment" 
          placeholder="写下你的评论..."
          :placeholder-style="'color: #999'"
          @focus="onInputFocus"
          @blur="onInputBlur"
        />
        <view class="send-btn" @click="sendComment" :class="{ active: newComment.trim() }">
          <text>发送</text>
        </view>
      </view>
    </view>

    <!-- 评论弹窗 -->
    <view class="modal-mask" v-if="showCommentsModal" @click.self="closeComments">
      <view class="modal-panel">
        <view class="modal-header">
          <text>全部评论 ({{ commentTotalCount }})</text>
          <view class="close" @click="closeComments">✕</view>
        </view>
        <scroll-view
          scroll-y
          class="modal-body"
          :lower-threshold="60"
          @scrolltolower="onScrollToLower"
          :refresher-enabled="true"
          :refresher-triggered="refreshing"
          @refresherrefresh="onRefresherRefresh"
        >
          <view class="cmt-item" v-for="c in comments" :key="c.id">
            <!-- 弹窗列表中亦提供右上角明显的采纳按钮/标记（仅保留固定按钮，移除行内按钮避免重叠） -->
            <view v-if="c.isAdopted" class="adopt-badge-fixed">
              <uni-icons type="checkbox-filled" color="#2ecc71" size="14"></uni-icons>
              <text style="margin-left:6rpx">已采纳</text>
            </view>
            <view v-else-if="canAdopt(c)" class="adopt-btn-fixed" :class="{ disabled: adoptLoadingId===c.id }" @click.stop="onClickAdopt(c)">
              <uni-icons type="checkbox" color="#2d8cf0" size="14"></uni-icons>
              <text style="margin-left:6rpx">{{ adoptLoadingId===c.id ? '采纳中...' : '采纳' }}</text>
            </view>
            <image class="cmt-avatar" :src="c.avatar || defaultAvatar" mode="aspectFill" />
            <view class="cmt-main">
              <view class="cmt-head">
                <text class="cmt-name">{{ c.username || '匿名用户' }}</text>
                <view class="cmt-right">
                  <text class="cmt-time">{{ c.time }}</text>
                </view>
              </view>
              <text class="cmt-text">{{ c.content }}</text>
              
              <view class="cmt-actions">
                <view class="act" @click.stop="onToggleCommentLike(c)">
                  <uni-icons :type="c.isLiked ? 'heart-filled' : 'heart'" :color="c.isLiked ? '#ff6b6b' : '#999'" size="14" />
                  <text :class="{ liked: c.isLiked }">{{ c.likes || 0 }}</text>
                </view>
                <view class="act" @click.stop="onToggleCommentCollect(c)">
                  <uni-icons :type="c.isCollected ? 'star-filled' : 'star'" :color="c.isCollected ? '#f5a623' : '#999'" size="14" />
                  <text :class="{ collected: c.isCollected }">{{ c.collects || 0 }}</text>
                </view>
              </view>
            </view>
          </view>
          <view v-if="comments.length === 0" class="empty">暂无评论</view>
          <view class="load-more" v-if="loadingComments">加载中...</view>
          <view class="load-more no-more" v-else-if="!hasMoreComments && comments.length > 0">没有更多了</view>
        </scroll-view>
        <view class="modal-input">
          <input class="modal-comment-input" v-model="newComment" placeholder="写下你的评论..." />
          <view class="modal-send" :class="{ active: newComment.trim() }" @click="sendComment">发送</view>
        </view>
      </view>
    </view>

    <!-- 编辑帖子弹窗（占位，等待后端更新接口） -->
    <view class="modal-mask" v-if="showEditModal" @click.self="showEditModal=false">
      <view class="modal-panel small">
        <view class="modal-header">
          <text>编辑帖子</text>
          <view class="close" @click="showEditModal=false">✕</view>
        </view>
        <view class="edit-form">
          <input class="edit-title" v-model="editForm.title" placeholder="请输入标题" />
          <textarea class="edit-content" v-model="editForm.content" placeholder="请输入内容" />
        </view>
        <view class="edit-actions">
          <view class="btn ghost" @click="showEditModal=false">取消</view>
          <view class="btn primary" @click="saveEdit">保存</view>
        </view>
      </view>
    </view>

    <!-- 分享弹窗：展示可复制/打开/系统分享的公开链接 -->
    <view class="modal-mask" v-if="showShareModal" @click.self="closeShareModal">
      <view class="modal-panel small">
        <view class="modal-header">
          <text>分享链接</text>
          <view class="close" @click="closeShareModal">✕</view>
        </view>
        <view class="share-body">
          <view class="desc">已生成可直接在浏览器打开的链接：</view>
          <textarea class="share-link" :value="shareLink" readonly ref="shareInput" @tap="selectShareLink"></textarea>
        </view>
        <view class="share-actions">
          <view class="btn primary" @click="copyAndCloseShare">复制并关闭</view>
          <view class="btn ghost" @click="copyShareLink">复制链接</view>
          <view class="btn" @click="systemShareLink">系统分享</view>
          <view class="btn" @click="openShareLink">浏览器打开</view>
        </view>
      </view>
    </view>
  </view>
</template>

<script>
import { getCircleInfo } from '@/api/circle'
import { addComment, getCommentList, adoptComment as adoptCommentApi } from '@/api/circleComment'
import { toggleCommentLike as toggleCommentLikeApi } from '@/api/commentLike'
import config from '@/config'
import { batchGetPatients } from '@/api/patient'
import { getDoctorDetail } from '@/api/doctor'
import storage from '@/utils/storage'
import constant from '@/utils/constant'
export default {
  data() {
    return {
      postId: '',
      routePatientId: '',
      routeAvatarOnEnter: '',
      newComment: '',
      postDetail: {
        id: '',
        username: '',
        patientId: '',
        // ...
      },
      showCommentsModal: false,
      showEditModal: false,
      showShareModal: false,
      shareLink: '',
      editForm: { title: '', content: '' },
      defaultAvatar: 'https://img.cdn.aliyun.dcloud.net.cn/uni-app/uniCloud/uni-id/avatar.png',
      comments: [],
      // 分页与加载状态
      pageNum: 1,
      pageSize: 10,
      totalTopLevel: 0,
      loadingComments: false,
      hasMoreComments: true,
      refreshing: false,
      // 回复状态
      replyingParentId: null,
      replyingHint: '',
      // 采纳加载中的评论ID（用于防重复点击）
      adoptLoadingId: null,
      // 调试开关：?debug=1 强制显示采纳按钮（仅用于联调）
      debugAdopt: false
    }
  },
  computed: {
    // 含二级回复的评论总数
    commentTotalCount() {
      if (!Array.isArray(this.comments)) return 0
      return this.comments.reduce((n, c) => n + 1 + ((c.replies && c.replies.length) || 0), 0)
    }
  },
  onLoad(options) {
    if (options.id) {
      this.postId = options.id
      // 路由调试开关
      if (options.debug === '1' || options.debug === 1 || options.debug === 'true') {
        this.debugAdopt = true
        try { console.warn('[adopt][debug] force enable adopt button via route param') } catch(_) {}
      }
      if (options.patientId) {
        this.routePatientId = options.patientId
        // 将路由中的 patientId 同步到 postDetail，便于模板与后续逻辑使用
        try { this.postDetail.patientId = options.patientId } catch (_) {}
      }
      // 若列表页传入 avatar/avatarUrl，则先行展示，并在有 patientId 时写入缓存
      if (options.avatar || options.avatarUrl) {
        try {
          let raw = options.avatar || options.avatarUrl
          try { raw = decodeURIComponent(raw) } catch (_) {}
          const ava = this.normalizeUrl(raw)
          this.postDetail.avatar = ava
          try { this.postDetail.avatarUrl = ava } catch (_) {}
          this.routeAvatarOnEnter = ava
          try { console.log('[detail] avatar from route param') } catch (_) {}
          const pid = options.patientId
          if (pid != null && pid !== '') {
            const KEY = 'patient:profile:map'
            try {
              const cache = uni.getStorageSync(KEY) || {}
              cache[String(pid)] = ava
              uni.setStorageSync(KEY, cache)
              try { console.log('[detail] seeded avatar to cache by pid from route') } catch (_) {}
            } catch (_) {}
          }
        } catch (_) {}
      }
      // 并行拉取详情与评论
      this.loadPostDetail()
      this.loadComments(true)
    }
  },
  methods: {
    // 将相对路径补全为绝对URL（用于头像、图片等）
    normalizeUrl(u) {
      const def = this.defaultAvatar
      if (!u) return def
      try {
        let s = String(u).trim()
        if (!s) return def
        // 已是绝对/协议相对/数据URL
        if (/^(https?:|data:)/i.test(s)) return s
        if (/^\/\//.test(s)) return 'https:' + s
        const base = (config && config.baseUrl) ? String(config.baseUrl).replace(/\/+$/, '') : ''
        s = s.replace(/^\/+/, '')
        return base ? `${base}/${s}` : `/${s}`
      } catch (_) {
        return def
      }
    },

    // 批量补全评论头像：后端未返回头像时，根据 patientId/doctorId 拉取资料
    async enrichCommentAvatars(comments = []) {
      try {
        if (!Array.isArray(comments) || comments.length === 0) return
        const def = this.defaultAvatar
        const need = comments.filter(c => !c.avatar || c.avatar === def)
        try { console.log('[enrich] total:', comments.length, 'need:', need.length) } catch (_) {}
        if (need.length === 0) return

        const patientIds = Array.from(
          new Set(
            need
              .filter(c => (Number(c.creatorType) === 1 || c.creatorType == null || c.creatorType === 0) && c.patientId != null)
              .map(c => Number(c.patientId))
              .filter(id => !isNaN(id))
          )
        )
        const doctorIds = Array.from(
          new Set(
            need
              .filter(c => (Number(c.creatorType) === 2 || c.creatorType == null || c.creatorType === 0) && c.doctorId != null)
              .map(c => Number(c.doctorId))
              .filter(id => !isNaN(id))
          )
        )

        // 1) 先从前端缓存读取患者头像（缓存键：patient:profile:map，结构 { [patientId]: avatarUrl }）
        const PATIENT_CACHE_KEY = 'patient:profile:map'
        let patientCache = {}
        try { patientCache = uni.getStorageSync(PATIENT_CACHE_KEY) || {} } catch (_) { patientCache = {} }

        const patientMap = new Map()
        patientIds.forEach(pid => {
          const cached = patientCache && patientCache[pid]
          if (cached) {
            const val = this.normalizeUrl(cached)
            const kNum = Number(pid)
            const kStr = String(pid)
            if (!isNaN(kNum)) patientMap.set(kNum, val)
            patientMap.set(kStr, val)
          }
        })

        // 仅对未命中缓存的患者再走批量接口
        const idsToFetch = patientIds.filter(pid => !patientMap.has(pid))
        try { console.log('[enrich] patientIds:', patientIds, 'cached hit:', Array.from(patientMap.keys()), 'toFetch:', idsToFetch) } catch (_) {}

        const [patientRes, doctorDetails] = await Promise.all([
          idsToFetch.length ? batchGetPatients(idsToFetch).catch(() => null) : Promise.resolve(null),
          // 目前无医生批量接口，逐个请求
          Promise.all(doctorIds.map(id => getDoctorDetail(id).then(r => ({ id, data: r?.data ?? r })).catch(() => null)))
        ])

        // 兼容 request 封装直接返回 data 的情况
        const patientList = (patientRes && (Array.isArray(patientRes) ? patientRes : patientRes.data)) || []
        try { console.log('[enrich] patientRes size:', Array.isArray(patientList) ? patientList.length : 'n/a') } catch (_) {}
        if (Array.isArray(patientList)) {
          patientList.forEach(p => {
            if (!p) return
            const avatar = this.normalizeUrl(
              p.avatar || p.avatarUrl || p.headImg || p.headPortrait || p.headUrl || p.imageUrl || p.photo || p.icon ||
              (p.user && (p.user.avatar || p.user.avatarUrl || p.user.headImg || p.user.headPortrait)) || def
            )
            const rawKey = (p.id ?? p.patientId ?? p.Id ?? p.patientID)
            const keyNum = Number(rawKey)
            const keyStr = String(rawKey)
            if (!isNaN(keyNum)) patientMap.set(keyNum, avatar)
            if (keyStr) patientMap.set(keyStr, avatar)
            // 写回缓存（对象键会自动转为字符串）
            try { if (keyStr) patientCache[keyStr] = avatar } catch (_) {}
          })
          // 持久化缓存
          try { uni.setStorageSync(PATIENT_CACHE_KEY, patientCache) } catch (_) {}
        }

        // 2) 兜底：若评论人为当前登录患者，直接用 Vuex 中的头像
        try {
          const curId = Number(this.$store && this.$store.state && this.$store.state.user && this.$store.state.user.id)
          const curAva = this.$store && this.$store.state && this.$store.state.user && this.$store.state.user.avatar
          if (curId && curAva) {
            const val = this.normalizeUrl(curAva)
            patientMap.set(curId, val)
            patientMap.set(String(curId), val)
          }
        } catch (_) {}

        const doctorMap = new Map()
        doctorDetails.filter(Boolean).forEach(({ id, data }) => {
          if (!data) return
          const d = data
          const avatar = this.normalizeUrl(
            d.avatar || d.avatarUrl || d.headImg || d.headPortrait || d.headUrl || d.imageUrl || d.photo || d.icon || d.doctorImage || d.image ||
            (d.user && (d.user.avatar || d.user.avatarUrl || d.user.headImg || d.user.headPortrait)) || def
          )
          const keyNum = Number(id)
          const keyStr = String(id)
          if (!isNaN(keyNum)) doctorMap.set(keyNum, avatar)
          if (keyStr) doctorMap.set(keyStr, avatar)
        })

        comments.forEach(c => {
          if (c.avatar && c.avatar !== def) return
          let type = Number(c.creatorType)
          const pidNum = Number(c.patientId)
          const didNum = Number(c.doctorId)
          const pidStr = c.patientId != null ? String(c.patientId) : ''
          const didStr = c.doctorId != null ? String(c.doctorId) : ''
          if ((isNaN(type) || type === 0) && (!isNaN(pidNum) || pidStr)) type = 1
          if ((isNaN(type) || type === 0) && (!isNaN(didNum) || didStr)) type = 2
          if (type === 1) {
            if (!isNaN(pidNum) && patientMap.has(pidNum)) c.avatar = patientMap.get(pidNum)
            else if (pidStr && patientMap.has(pidStr)) c.avatar = patientMap.get(pidStr)
          } else if (type === 2) {
            if (!isNaN(didNum) && doctorMap.has(didNum)) c.avatar = doctorMap.get(didNum)
            else if (didStr && doctorMap.has(didStr)) c.avatar = doctorMap.get(didStr)
          }
        })
        try { console.log('[enrich] after assign sample:', comments.slice(0,3).map(x => ({id:x.id, type:x.creatorType, pid:x.patientId, did:x.doctorId, ava:x.avatar}))) } catch (_) {}
        try { this.$forceUpdate && this.$forceUpdate() } catch (_) {}
      } catch (e) {
        // 静默失败，不影响主流程
        try { console.warn('补全评论头像失败', e) } catch (_) {}
      }
    },
    goBack() {
      uni.navigateBack()
    },
    openMore() {
      uni.showActionSheet({
        itemList: ['编辑帖子', '分享'],
        success: (res) => {
          if (res.tapIndex === 0) {
            this.editForm.title = this.postDetail.title
            this.editForm.content = this.postDetail.content
            this.showEditModal = true
          }
          if (res.tapIndex === 1) {
            // 打开分享弹窗，让用户查看并选择复制/打开
            try {
              const link = this.buildShareLink(this.postId)
              this.shareLink = link
              this.showShareModal = true
            } catch (e) {
              console.error('生成分享链接失败', e)
              uni.showToast({ title: '分享失败', icon: 'none' })
            }
          }
        }
      })
    },

    // 构造公开分享链接：指向后端直出HTML的公开页，无需H5
    buildShareLink(id) {
      const pid = id != null ? String(id) : String(this.postId || this.postDetail?.id || '')
      if (!pid) throw new Error('缺少帖子ID')
      // 通过网关的后端公开地址（与前端接口同域），确保不依赖H5即可访问
      const apiBase = (config && config.baseUrl ? String(config.baseUrl) : '').replace(/\/$/, '')
      // 注意：前端圈子API前缀为 /circle/circle，因此公开页完整路径如下
      return `${apiBase}/circle/circle/public/${encodeURIComponent(pid)}`
    },
    // 复制分享链接
    copyShareLink() {
      const link = this.shareLink || this.buildShareLink(this.postId)
      uni.setClipboardData({
        data: link,
        success: () => uni.showToast({ title: '已复制链接', icon: 'success' })
      })
    },
    // 打开浏览器（H5 直接跳转；App/小程序尝试系统浏览）
    openShareLink() {
      const link = this.shareLink || this.buildShareLink(this.postId)
      try {
        // H5：新开窗口
        if (typeof window !== 'undefined') {
          window.open(link, '_blank')
          // 成功触发后关闭弹窗
          this.closeShareModal()
          return
        }
      } catch (_) {}
      // 其它端：尝试使用内置 webview
      try {
        uni.navigateTo({ url: `/pages/common/webview/index?url=${encodeURIComponent(link)}` })
        this.closeShareModal()
      } catch (_) {}
    },
    selectShareLink() {
      uni.showActionSheet({
        itemList: ['复制链接', '打开链接'],
        success: (res) => {
          if (res.tapIndex === 0) {
            this.copyShareLink()
          } else if (res.tapIndex === 1) {
            this.openShareLink()
          }
        }
      })
    },
    copyAndCloseShare() {
      this.copyShareLink()
      this.closeShareModal()
    },
    // 系统分享（若支持）
    systemShareLink() {
      const link = this.shareLink || this.buildShareLink(this.postId)
      try {
        if (typeof window !== 'undefined' && window.navigator && typeof window.navigator.share === 'function') {
          window.navigator.share({
            title: this.postDetail?.title || '帖子详情',
            text: '分享一个病友圈帖子',
            url: link
          }).catch(() => {})
        } else {
          this.copyShareLink()
        }
      } catch (_) {
        this.copyShareLink()
      }
    },
    closeShareModal() { this.showShareModal = false },
    openComments() {
      this.showCommentsModal = true
      this.loadComments(true)
    },
    closeComments() { this.showCommentsModal = false },
    // 楼主头像点击：跳转到病友圈列表并按 patientId 过滤
    onClickPostAvatar() {
      const pid = this.postDetail && (this.postDetail.patientId || this.routePatientId)
      try { console.log('[avatar-click] post avatar clicked, pid=', pid) } catch (_) {}
      if (pid !== undefined && pid !== null && String(pid) !== '') {
        const name = this.postDetail?.username || ''
        const ava = this.postDetail?.avatar || this.postDetail?.avatarUrl || ''
        const url = `/pages/community/patient?patientId=${encodeURIComponent(pid)}&username=${encodeURIComponent(name)}&avatar=${encodeURIComponent(ava)}`
        uni.showToast({ title: '跳转病友圈', icon: 'none', duration: 800 })
        uni.navigateTo({ url })
      } else {
        // 兜底：即便没有 patientId，也先跳到列表页，验证事件是否触发
        uni.showToast({ title: '未找到患者ID，先返回列表', icon: 'none', duration: 1000 })
        uni.navigateTo({ url: '/pages/community/index' })
      }
    },
    // 评论头像点击：患者 -> 病友圈；医生 -> 医生详情
    onClickCommentAvatar(comment) {
      if (!comment) return
      let type = Number(comment.creatorType)
      const pid = comment.patientId
      const did = comment.doctorId
      if ((isNaN(type) || type === 0) && (pid !== undefined && pid !== null && String(pid) !== '')) type = 1
      if ((isNaN(type) || type === 0) && (did !== undefined && did !== null && String(did) !== '')) type = 2
      if (type === 2 && did) {
        const url = `/pages/doctors/detail?doctorId=${encodeURIComponent(did)}`
        uni.navigateTo({ url })
        return
      }
      if (type === 1 && pid) {
        const name = comment?.username || ''
        const ava = comment?.avatar || ''
        const url = `/pages/community/patient?patientId=${encodeURIComponent(pid)}&username=${encodeURIComponent(name)}&avatar=${encodeURIComponent(ava)}`
        uni.navigateTo({ url })
        return
      }
      if (pid !== undefined && pid !== null && String(pid) !== '') {
        const name = comment?.username || ''
        const ava = comment?.avatar || ''
        const url = `/pages/community/patient?patientId=${encodeURIComponent(pid)}&username=${encodeURIComponent(name)}&avatar=${encodeURIComponent(ava)}`
        uni.navigateTo({ url })
      }
    },
    // 将后端 ApiCircleController 返回（一级+二级）映射为前端展示结构
    mapApiComments(list = []) {
      if (!Array.isArray(list)) return []
      const def = this.defaultAvatar
      return list.map(item => {
        const username = (
          item?.creatorName || item?.userNickname || item?.nickName || item?.nickname || item?.userName ||
          item?.creatorName || item?.authorName || item?.createByName || item?.createBy
        ) || '匿名用户'
        let avatar = (
          item?.creatorAvatar || item?.avatar || item?.avatarUrl || item?.headImg || item?.headPortrait ||
          (item.user && (item.user.avatar || item.user.avatarUrl))
        ) || def
        avatar = this.normalizeUrl(avatar)
        const timeRaw = item?.commentTime || item?.comment_time || item?.createTime || item?.create_time || item?.gmtCreate
        const liked = !!(item?.isLiked ?? item?.liked ?? item?.haveLiked)
        const likes = item?.likeCount ?? item?.like_count ?? item?.likes ?? 0
        const isAdopted = !!(item?.isAdopted || item?.adopted || item?.adoptFlag || item?.adoptedFlag || item?.adopt === 1 || item?.adoptStatus === 1 || item?.adopt_status === 1)
        // 兼容多种字段命名，并统一类型（含字符串枚举）
        const ctRaw = item?.creatorType ?? item?.creator_type ?? item?.type ?? 0
        let creatorType = Number(ctRaw)
        if (isNaN(creatorType)) {
          const s = String(ctRaw || '').toLowerCase()
          if (s === 'patient' || s === 'p' || s === '1' || s === '患者') creatorType = 1
          else if (s === 'doctor' || s === 'd' || s === '2' || s === '医生') creatorType = 2
          else creatorType = 0
        }
        const patientId = item?.patientId ?? item?.patientID ?? item?.patient_id ?? item?.pid ?? item?.userId ?? item?.user_id ?? item?.uid
        const doctorId = item?.doctorId ?? item?.doctorID ?? item?.doctor_id ?? item?.did

        const top = {
          id: item?.id,
          username,
          avatar: avatar || def,
          time: this.formatShortTime(timeRaw),
          content: item?.content || '',
          likes: typeof likes === 'number' ? likes : 0,
          isLiked: liked,
          isAdopted,
          // 为后续头像补全保留身份与ID
          creatorType,
          patientId,
          doctorId,
          replies: []
        }
        const childList = (
          Array.isArray(item?.children) ? item.children :
          Array.isArray(item?.childList) ? item.childList :
          Array.isArray(item?.replies) ? item.replies :
          Array.isArray(item?.replyList) ? item.replyList : []
        )
        top.replies = childList.map(ct => {
          const cUser = (
            ct?.creatorName || ct?.userNickname || ct?.nickName || ct?.nickname || ct?.userName
          ) || '匿名用户'
          const cTime = ct?.commentTime || ct?.comment_time || ct?.createTime || ct?.create_time || ct?.gmtCreate
          return {
            id: ct?.id,
            username: cUser,
            content: ct?.content || '',
            time: this.formatShortTime(cTime)
          }
        })
        return top
      })
    },
    async loadComments(reset = false) {
      if (!this.postId) return
      if (this.loadingComments) return
      if (reset) {
        this.pageNum = 1
        this.hasMoreComments = true
        this.totalTopLevel = 0
        this.comments = []
      }
      if (!this.hasMoreComments) return
      this.loadingComments = true
      try {
        const res = await getCommentList(Number(this.postId), this.pageNum, this.pageSize)
        const data = res?.data
        let rows = []
        let total = 0
        if (Array.isArray(data)) {
          // 兼容旧返回（一次性返回全部）
          rows = data
          total = data.length
        } else if (data && typeof data === 'object') {
          rows = Array.isArray(data.rows) ? data.rows : []
          total = typeof data.total === 'number' ? data.total : 0
        }

        const mapped = this.mapApiComments(rows)
        if (this.pageNum === 1) {
          this.comments = mapped
        } else {
          this.comments = this.comments.concat(mapped)
        }
        this.totalTopLevel = total || this.totalTopLevel

        // hasMore 判定：根据顶级评论分页总量
        const loadedTopLevel = this.comments.length
        if (this.totalTopLevel > 0) {
          this.hasMoreComments = loadedTopLevel < this.totalTopLevel
        } else {
          // 后端没给总数时，用当前页条数是否小于 pageSize 判断
          this.hasMoreComments = mapped.length >= this.pageSize
        }

        // 预增页码
        if (this.hasMoreComments) {
          this.pageNum += 1
        }

        // 补全头像（后端未返回头像字段时）
        await this.enrichCommentAvatars(this.comments)

        // 同步评论计数（用于展示）
        this.postDetail.commentCount = this.comments.reduce((n, c) => n + 1 + ((c.replies && c.replies.length) || 0), 0)
      } catch (e) {
        console.error('加载评论失败', e)
        uni.showToast({ title: '加载评论失败', icon: 'none' })
      } finally {
        this.loadingComments = false
        if (this.refreshing) {
          this.refreshing = false
        }
        // 停止页面级下拉刷新动画
        try { uni.stopPullDownRefresh() } catch (_) {}
      }
    },
    onScrollToLower() {
      // 触底加载下一页
      if (this.hasMoreComments) {
        this.loadComments(false)
      }
    },
    onRefresherRefresh() {
      // scroll-view 原生下拉刷新
      if (this.loadingComments) return
      this.refreshing = true
      this.loadComments(true)
    },
    // 页面级下拉刷新（需在 pages.json 对应页面开启 enablePullDownRefresh）
    onPullDownRefresh() {
      if (this.loadingComments) {
        try { uni.stopPullDownRefresh() } catch (_) {}
        return
      }
      this.loadComments(true).finally(() => {
        try { uni.stopPullDownRefresh() } catch (_) {}
      })
    },
    // 将后端 PatientCircle -> 前端展示结构的映射
    mapCircleDetail(raw = {}) {
      const isAnonymous = raw.anonymous === true || raw.isAnonymous === true || raw.is_anonymous === 1
      const defaultAvatar = 'https://img.cdn.aliyun.dcloud.net.cn/uni-app/uniCloud/uni-id/avatar.png'
      // 用户名多字段兼容
      let username = (
        raw.patientName || raw.userNickname || raw.nickName || raw.nickname || raw.userName ||
        raw.creatorName || raw.authorName || raw.createByName || raw.createBy
      ) || ''
      // 头像多字段兼容
      let avatar = (
        raw.patientAvatar || raw.userAvatar || raw.avatar || raw.avatarUrl || raw.headImg || raw.headPortrait ||
        (raw.user && (raw.user.avatar || raw.user.avatarUrl))
      ) || ''
      if (isAnonymous) {
        username = '匿名用户'
        avatar = defaultAvatar
      }
      if (!username) username = '匿名用户'
      if (!avatar) avatar = defaultAvatar
      avatar = this.normalizeUrl(avatar)

      // 图片字段兼容：数组/字符串(JSON/逗号/空格分隔)/单链接兜底
      let images = []
      const imgRaw = (
        raw.images ?? raw.pics ?? raw.imageUrls ?? raw.imagesUrls ??
        raw.image ?? raw.imagesUrl ?? raw.picsUrl ?? null
      )
      if (Array.isArray(imgRaw)) {
        images = imgRaw
      } else if (typeof imgRaw === 'string') {
        const s = String(imgRaw).trim()
        try {
          if (s.startsWith('[') && s.endsWith(']')) {
            const arr = JSON.parse(s)
            if (Array.isArray(arr)) images = arr
          } else {
            images = s.split(/[\s,]+/).map(v => v.trim()).filter(Boolean)
          }
        } catch (e) {
          images = s.split(/[\s,]+/).map(v => v.trim()).filter(Boolean)
        }
      }
      // 若仍为空，尝试单链接字段
      if (!images || images.length === 0) {
        const single = raw.firstUrl || raw.coverUrl || raw.thumbnail || raw.thumbUrl || raw.cover
        if (single && typeof single === 'string') images = [single]
      }
      // 去重与基础校验
      images = Array.from(new Set(
        (images || [])
          .map(u => typeof u === 'string' ? u.trim() : '')
          .filter(u => !!u && /^(https?:)?\//.test(u))
      ))

      // 标签：科室/疾病
      const tags = []
      if (raw.deptName) tags.push(raw.deptName)
      if (raw.diseaseName) tags.push(raw.diseaseName)

      // 提取患者ID（多字段兼容）
      const patientId = (
        raw.patientId ?? raw.patientID ?? raw.patient_id ?? raw.pid ?? raw.userId ?? raw.user_id ?? raw.uid ?? raw.creatorId ?? raw.authorId
      )

      return {
        id: raw.id || raw.circleId || raw.postId || raw.idStr,
        username,
        avatar,
        avatarUrl: avatar,
        // 兼容下划线命名：publish_time/create_time
        time: this.formatShortTime(
          raw.publishTime || raw.publish_time || raw.createTime || raw.create_time || raw.gmtCreate || ''
        ),
        patientId,
        title: raw.title || '',
        content: raw.content || '',
        images,
        tags,
        likes: raw.likeCount || raw.likes || 0,
        collects: raw.collectCount || raw.favorites || 0,
        isLiked: false,
        isCollected: false,
        isFollowed: false,
        diseaseName: raw.diseaseName || raw.disease_name,
        // 科室/医院名称后端未联表时可能为空，这里先兼容可能的字段名
        deptName: raw.deptName || raw.departmentName || raw.department_name,
        diseaseDetail: raw.diseaseDetail || raw.disease_detail,
        treatmentProcess: raw.treatmentProcess || raw.treatment_process,
        hospitalName: raw.hospitalName || raw.hospital_name,
        startTime: raw.startTime || raw.start_time,
        endTime: raw.endTime || raw.end_time,
        commentCount: raw.adviceCount || 0,
        viewCount: raw.viewCount || raw.views || 0
      }
    },

    async loadPostDetail() {
      try {
        const res = await getCircleInfo(this.postId)
        // 后端统一返回 PatientCircle，兼容不同返回结构
        const raw = res?.data ?? res?.row ?? res?.record ?? res
        if (!raw || (typeof raw !== 'object')) {
          throw new Error('empty detail')
        }
        this.postDetail = this.mapCircleDetail(raw)
        // 覆盖状态：若本地缓存已标记该帖子已结束，则直接显示已结束
        try {
          const KEY = 'circle:ended:map'
          const cache = uni.getStorageSync(KEY) || {}
          if (cache && (cache[this.postId] || cache[String(this.postId)])) {
            this.postDetail.isEnded = true
            try { this.postDetail.statusText = '已结束' } catch (_) {}
          }
        } catch (_) {}
        // 若进入时已携带头像，先用该头像覆盖映射默认值（缓存命中将继续覆盖）
        if (this.routeAvatarOnEnter) {
          this.postDetail.avatar = this.routeAvatarOnEnter
          try { this.postDetail.avatarUrl = this.routeAvatarOnEnter } catch (_) {}
        }
        // 详情页：若拿到患者ID，优先从前端缓存覆盖楼主头像
        const PATIENT_CACHE_KEY = 'patient:profile:map'
        try {
          const pid = this.routePatientId || this.postDetail.patientId
          if (pid != null && pid !== '') {
            const cache = uni.getStorageSync(PATIENT_CACHE_KEY) || {}
            const hit = cache[pid] || cache[String(pid)]
            if (hit) {
              this.postDetail.avatar = this.normalizeUrl(hit)
              try { console.log('[detail] avatar from cache by pid', pid) } catch (_) {}
            } else {
              // 兜底：若为当前登录患者本人，从 storage 读取自己的头像
              try {
                const uid = storage.get(constant.id)
                const uav = storage.get(constant.avatar)
                if (uid && String(uid) === String(pid) && uav) {
                  this.postDetail.avatar = this.normalizeUrl(uav)
                  try { console.log('[detail] avatar from storage (self) by uid', uid) } catch (_) {}
                  // 同步写回患者头像缓存，便于后续直接命中
                  try {
                    const cache2 = uni.getStorageSync(PATIENT_CACHE_KEY) || {}
                    cache2[String(uid)] = this.postDetail.avatar
                    uni.setStorageSync(PATIENT_CACHE_KEY, cache2)
                    try { console.log('[detail] wrote self avatar to cache', PATIENT_CACHE_KEY) } catch (_) {}
                  } catch (_) {}
                }
              } catch (_) {}
            }
          }
        } catch (e) {
          console.error('loadPostDetail error', e)
        }
      } catch (e) {
        console.error('加载帖子详情失败', e)
        uni.showToast({ title: '加载详情失败', icon: 'none' })
        setTimeout(() => { uni.navigateBack() }, 1200)
      }
    },
    toggleFollow() {
      this.postDetail.isFollowed = !this.postDetail.isFollowed
      uni.showToast({
        title: this.postDetail.isFollowed ? '关注成功' : '取消关注',
        icon: 'none'
      })
    },
    
    toggleLike() {
      this.postDetail.isLiked = !this.postDetail.isLiked
      this.postDetail.likes += this.postDetail.isLiked ? 1 : -1
    },
    
    toggleCollect() {
      this.postDetail.isCollected = !this.postDetail.isCollected
      this.postDetail.collects += this.postDetail.isCollected ? 1 : -1
      uni.showToast({
        title: this.postDetail.isCollected ? '收藏成功' : '取消收藏',
        icon: 'none'
      })
    },
    
    previewImage(current, urls) {
      uni.previewImage({
        current,
        urls
      })
    },
    
    async toggleCommentLike(comment) {
      try {
        const res = await toggleCommentLikeApi(comment.id)
        const data = res?.data ?? res
        if (data) {
          comment.isLiked = !!(data.isLiked ?? data.liked)
          if (typeof data.likeCount === 'number') {
            comment.likes = data.likeCount
          } else {
            // 回退策略
            comment.likes += comment.isLiked ? 1 : -1
          }
        }
      } catch (e) {
        console.error('评论点赞失败', e)
        uni.showToast({ title: '点赞失败', icon: 'none' })
      }
    },
    // 弹窗内点赞复用
    onToggleCommentLike(c) { this.toggleCommentLike(c) },
    // 本地收藏占位（待后端接口）
    onToggleCommentCollect(c) {
      c.isCollected = !c.isCollected
      c.collects = Math.max(0, (c.collects || 0) + (c.isCollected ? 1 : -1))
    },
    
    replyToComment(comment) {
      if (!comment) return
      this.replyingParentId = comment.id
      const uname = comment.username || '匿名用户'
      this.replyingHint = `回复 ${uname}`
      // 仅在输入框预填@，实际以 parentId 作为后端关联
      this.newComment = this.newComment && this.newComment.trim() ? this.newComment : `@${uname} `
      // 可选：滚动到输入框位置/聚焦
      this.$nextTick(() => {
        // 预留聚焦逻辑
      })
    },
    
    async sendComment() {
      const text = (this.newComment || '').trim()
      if (!text) return
      try {
        // 发送参数对齐后端 DTO：必须 circleId、content；可选 parentId、creatorType、creatorName
        const payload = {
          circleId: Number(this.postId),
          content: text
        }
        // 回复场景：带上父评论ID
        if (this.replyingParentId) {
          payload.parentId = this.replyingParentId
        }
        // 角色类型：默认患者端=1，如后续接入医生端可扩展判断
        payload.creatorType = 1
        // 填充名称（用于后端展示/冗余）
        try {
          const store = this.$store && this.$store.state && this.$store.state.user
          const name = (store && (store.name || store.username)) || this.postDetail?.username || ''
          if (name) payload.creatorName = name
        } catch (_) {}

        await addComment(payload)
        // 清理输入与回复状态
        this.newComment = ''
        this.replyingParentId = null
        this.replyingHint = ''
        await this.loadComments(true)
        uni.showToast({ title: '评论成功', icon: 'success' })
      } catch (e) {
        console.error('发表评论失败', e)
        let msg = '评论失败'
        try { msg = e?.data?.msg || e?.message || msg } catch (_) {}
        uni.showToast({ title: String(msg), icon: 'none' })
      }
    },
    saveEdit() {
      // 预留更新接口，如：updateCircle(this.postId, this.editForm)
      uni.showToast({ title: '更新接口待后端提供', icon: 'none' })
      this.showEditModal = false
    },
    
    formatTime(date) {
      const year = date.getFullYear()
      const month = String(date.getMonth() + 1).padStart(2, '0')
      const day = String(date.getDate()).padStart(2, '0')
      const hour = String(date.getHours()).padStart(2, '0')
      const minute = String(date.getMinutes()).padStart(2, '0')
      return `${year}-${month}-${day} ${hour}:${minute}`
    },
    
    // 将后端时间字符串/时间戳格式化为简短显示（YYYY-MM-DD HH:mm）
    formatShortTime(val) {
      if (!val) return ''
      try {
        let d = null
        if (typeof val === 'number') {
          d = new Date(val > 1e12 ? val : val * 1000)
        } else if (typeof val === 'string') {
          const s = val.trim()
          if (!s) return ''
          // 兼容 iOS：将 2025-05-28 12:34:56 或 ISO 字符串转换
          const normalized = s.replace(/-/g, '/').replace('T', ' ').replace(/\.\d+Z?$/, '')
          const ts = Date.parse(normalized)
          if (!isNaN(ts)) d = new Date(ts)
        } else if (val instanceof Date) {
          d = val
        }
        if (!d || isNaN(d.getTime())) return typeof val === 'string' ? val : ''
        return this.formatTime(d)
      } catch (e) {
        return typeof val === 'string' ? val : ''
      }
    },
    
    onInputFocus() {
      // 输入框聚焦处理
    },
    
    onInputBlur() {
      // 输入框失焦处理
    },

    // 采纳相关
    // 只有帖子作者（患者）且评论为医生、且当前帖子尚未采纳过，才显示采纳
    canAdopt(c) {
      if (!c) return false
      try {
        const uid = this.$store?.state?.user?.id || storage.get(constant.id)
        const ownerId = this.postDetail?.patientId
        const isOwner = uid != null && ownerId != null && String(uid) === String(ownerId)
        const isDoctor = (Number(c.creatorType) === 2) || !!c.doctorId
        const anyAdopted = Array.isArray(this.comments) && this.comments.some(x => x && x.isAdopted)
        // 调试模式下，强制显示采纳按钮（无条件），用于联调点击后端接口
        if (this.debugAdopt) return true
        return isOwner && isDoctor && !c.isAdopted && !anyAdopted
      } catch (e) { return false }
    },
    onClickAdopt(c) {
      try { console.log('[adopt] click id=', c && c.id) } catch (_) {}
      if (!this.canAdopt(c)) { try { console.log('[adopt] canAdopt=false') } catch (_) {} return }
      if (this.adoptLoadingId) { try { console.log('[adopt] loading, ignore') } catch (_) {} return }

      const doAdopt = () => {
        try { console.log('[adopt] start request id=', c && c.id) } catch (_) {}
        this.adoptCommentAction(c)
      }

      // 优先弹确认框；若失败或环境不支持，则降级为直接执行
      try {
        if (uni && typeof uni.showModal === 'function') {
          uni.showModal({
            title: '确认采纳',
            content: '采纳后将发放悬赏金额给该医生，是否继续？',
            confirmText: '采纳',
            success: (res) => { if (res && res.confirm) doAdopt() },
            fail: () => { try { console.warn('[adopt] showModal fail, fallback direct') } catch (_) {} ; doAdopt() }
          })
        } else {
          doAdopt()
        }
      } catch (e) {
        try { console.warn('[adopt] showModal exception, fallback', e) } catch (_) {}
        doAdopt()
      }
    },
    async adoptCommentAction(comment) {
      if (!comment || !comment.id) return
      if (this.adoptLoadingId) return
      this.adoptLoadingId = comment.id
      try {
        const res = await adoptCommentApi(comment.id)
        // 成功后前端状态更新
        comment.isAdopted = true
        if (Array.isArray(this.comments)) {
          // 让其他评论不再显示采纳按钮
          this.comments = this.comments.map(x => x.id === comment.id ? { ...x, isAdopted: true } : x)
        }
        this.postDetail.isEnded = true
        try { this.postDetail.statusText = '已结束' } catch (_) {}
        // 持久化“已结束”状态，列表页与下次进入保持一致
        try {
          const KEY = 'circle:ended:map'
          const map = uni.getStorageSync(KEY) || {}
          map[String(this.postId)] = true
          uni.setStorageSync(KEY, map)
          try { uni.$emit && uni.$emit('circle-ended', { id: this.postId }) } catch (_) {}
        } catch (_) {}
        uni.showToast({ title: '采纳成功', icon: 'success' })
      } catch (e) {
        console.error('采纳失败', e)
        uni.showToast({ title: (e && e.msg) || '采纳失败，请稍后重试', icon: 'none' })
      } finally {
        this.adoptLoadingId = null
      }
    }
  }
}
</script>

<style lang="scss" scoped>
.container {
  background-color: #f5f5f5;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

.header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 20rpx 30rpx;
  padding-top: calc(20rpx + var(--status-bar-height));
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  border-bottom: 0;
  
  .back-btn {
    width: 60rpx;
    height: 60rpx;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: rgba(255,255,255,0.2);
    border-radius: 30rpx;
  }
  
  .header-title {
    font-size: 34rpx;
    font-weight: 600;
    color: #fff;
  }
  
  .header-right {
    width: 60rpx;
    height: 60rpx;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: rgba(255,255,255,0.2);
    border-radius: 30rpx;
  }
}

.content {
  flex: 1;
  padding-bottom: 120rpx;
}

  .post-detail {
  background-color: #fff;
  margin: 20rpx;
  margin-bottom: 20rpx;
  border-radius: 16rpx;
  overflow: hidden;
  box-shadow: 0 8rpx 24rpx rgba(0,0,0,0.06);
  
  .user-info {
    display: flex;
    align-items: center;
    padding: 30rpx;
    
    .avatar {
      width: 80rpx;
      height: 80rpx;
      border-radius: 50%;
      margin-right: 20rpx;
    }
    
    .user-content {
      flex: 1;
      
      .user-name {
        font-size: 28rpx;
        font-weight: 600;
        color: #333;
        margin-bottom: 8rpx;
      }
      
      .post-time {
        font-size: 24rpx;
        color: #999;
      }
    }
    
    .follow-btn {
      padding: 10rpx 22rpx;
      border: 1rpx solid #ffffff;
      border-radius: 24rpx;
      background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
      box-shadow: 0 4rpx 10rpx rgba(102,126,234,0.25);
      
      text {
        font-size: 24rpx;
        color: #fff;
      }
      
      &.followed {
        background: #f2f3f5;
        border-color: #e5e6eb;
        
        text {
          color: #666;
        }
      }
    }
  }
  
  .post-content {
    padding: 0 30rpx 20rpx;
    
    .post-title {
      display: block;
      font-size: 32rpx;
      font-weight: 600;
      color: #333;
      margin-bottom: 20rpx;
      line-height: 1.4;
    }

    // 标题下的元信息行
    .post-meta {
      display: flex;
      align-items: center;
      flex-wrap: wrap;
      gap: 14rpx;
      margin-bottom: 14rpx;

      .meta-item {
        display: inline-flex;
        align-items: center;
        padding: 8rpx 12rpx;
        background: #f7f8fa;
        border-radius: 999rpx;

        text {
          font-size: 22rpx;
          color: #888;
          margin-left: 6rpx;
        }
      }

      .meta-item.ended {
        background: #ecfff3;
        
        text {
          color: #2ecc71;
        }
      }

      .meta-tags {
        display: inline-flex;
        align-items: center;
        flex-wrap: wrap;
        gap: 10rpx;

        .meta-tag {
          padding: 6rpx 12rpx;
          background-color: #eef2ff;
          color: #5c6ac4;
          font-size: 22rpx;
          border-radius: 999rpx;
        }
      }
    }
    
    .post-text {
      display: block;
      font-size: 28rpx;
      color: #303133;
      line-height: 1.9;
      margin-bottom: 18rpx;
      word-break: break-word;
      white-space: pre-wrap;
    }
  }
  
  /* 图片宫格（QQ 朋友圈风格） */
  .post-images {
    display: grid;
    gap: 10rpx;
    margin-bottom: 22rpx;

    &.one {
      grid-template-columns: 1fr;
      .image-item {
        width: 100%;
        height: 420rpx;
        border-radius: 12rpx;
        overflow: hidden;
      }
    }

    &.two {
      grid-template-columns: 1fr 1fr;
      .image-item {
        height: 300rpx;
        border-radius: 12rpx;
        overflow: hidden;
      }
    }

    &.grid {
      grid-template-columns: repeat(3, 1fr);
      .image-item {
        position: relative;
        width: 100%;
        aspect-ratio: 1 / 1;
        border-radius: 12rpx;
        overflow: hidden;
      }
    }

    .image-item image {
      width: 100%;
      height: 100%;
    }

    .more-mask {
      position: absolute;
      inset: 0;
      background: rgba(0,0,0,0.45);
      display: flex;
      align-items: center;
      justify-content: center;
      text {
        color: #fff;
        font-size: 28rpx;
        font-weight: 600;
      }
    }
  }
  
  .post-tags {
    padding: 0 30rpx 20rpx;
    
    .tag {
      display: inline-block;
      padding: 8rpx 16rpx;
      background-color: #f0f8ff;
      color: #007aff;
      font-size: 24rpx;
      border-radius: 16rpx;
      margin-right: 10rpx;
    }
  }
  
  /* 病症信息块样式 */
  .medical-info {
    padding: 0 30rpx 20rpx;
    display: flex;
    flex-direction: column;
    gap: 12rpx;

    .info-row {
      display: flex;
      align-items: flex-start;
      gap: 12rpx;
    }

    .info-block {
      display: flex;
      flex-direction: column;
      gap: 8rpx;
    }

    .label {
      min-width: 120rpx;
      font-size: 24rpx;
      color: #666;
      line-height: 1.8;
    }

    .value {
      flex: 1;
      font-size: 26rpx;
      color: #303133;
      line-height: 1.8;
      word-break: break-word;
    }

    .value.block {
      background: #f8f8f8;
      border-radius: 10rpx;
      padding: 12rpx;
      white-space: pre-wrap;
    }
  }
  
  .post-status-badge {
    padding: 16rpx 24rpx 6rpx;
    margin: 0 20rpx 12rpx;
    border-top: 1rpx solid #f7f8fa;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 24rpx;
    .status-chip { color: #2ba245; }
    .status-chip.ended { color: #ff4d4f; }
  }
  
  .post-stats {
    display: flex;
    align-items: center;
    padding: 16rpx 24rpx 6rpx;
    margin: 0 20rpx 12rpx;
    border-top: 1rpx solid #f7f8fa;
  
    .stat-item {
      display: inline-flex;
      align-items: center;
      padding: 10rpx 16rpx;
      background: #f7f8fa;
      border-radius: 999rpx;
      margin-right: 14rpx;
      
      text {
        font-size: 24rpx;
        color: #666;
        margin-left: 8rpx;
        
        &.liked { color: #ff6b6b; }
        &.collected { color: #f5a623; }
      }
    }
  }
}

.comments-section {
  background-color: #fff;
  
  .comments-header {
    padding: 30rpx;
    border-bottom: 1rpx solid #f0f0f0;
    
    .comments-title {
      font-size: 28rpx;
      font-weight: 600;
      color: #333;
    }
  }
  
  .comments-list {
    .comment-item {
      display: flex;
      position: relative;
      padding: 30rpx;
      border-bottom: 1rpx solid #f8f8f8;
      
      .comment-avatar {
        width: 60rpx;
        height: 60rpx;
        border-radius: 50%;
        margin-right: 20rpx;
        flex-shrink: 0;
      }
      
      .comment-content {
        flex: 1;
        
        .comment-header {
          display: flex;
          align-items: center;
          justify-content: space-between;
          margin-bottom: 10rpx;
          
          .comment-username {
            font-size: 26rpx;
            font-weight: 600;
            color: #333;
          }
          
          .comment-time {
            font-size: 22rpx;
            color: #999;
          }
        }
        
        .comment-text {
          display: block;
          font-size: 26rpx;
          color: #666;
          line-height: 1.5;
          margin-bottom: 15rpx;
        }
        
        .replies {
          background-color: #f8f8f8;
          border-radius: 8rpx;
          padding: 15rpx;
          margin-bottom: 15rpx;
          
          .reply-item {
            margin-bottom: 8rpx;
            
            &:last-child {
              margin-bottom: 0;
            }
            
            .reply-username {
              font-size: 24rpx;
              color: #007aff;
              font-weight: 600;
            }
            
            .reply-text {
              font-size: 24rpx;
              color: #666;
            }
            
            .reply-time {
              font-size: 22rpx;
              color: #999;
              margin-left: 10rpx;
            }
          }
        }
        
        .comment-actions {
          display: flex;
          align-items: center;
          
          .action-btn {
            display: flex;
            align-items: center;
            margin-right: 30rpx;
            
            text {
              font-size: 22rpx;
              color: #999;
              margin-left: 6rpx;
              
              &.liked {
                color: #ff6b6b;
              }
            }
          }
        }
      }
    }
  }
}

.comment-input-section {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  background-color: #fff;
  border-top: 1rpx solid #eee;
  padding: 20rpx 30rpx;
  padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
  
  .input-container {
    display: flex;
    align-items: center;
    
    .comment-input {
      flex: 1;
      height: 70rpx;
      background-color: #f8f8f8;
      border-radius: 35rpx;
      padding: 0 20rpx;
      font-size: 26rpx;
      margin-right: 20rpx;
    }
    
    .send-btn {
      padding: 15rpx 30rpx;
      background-color: #e0e0e0;
      border-radius: 20rpx;
      
      text {
        font-size: 26rpx;
        color: #999;
      }
      
      &.active {
        background-color: #007aff;
        
        text {
          color: #fff;
        }
      }
    }
  }
}

/* 通用弹窗样式（评论弹窗、编辑弹窗） */
.modal-mask {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.45);
  display: flex;
  align-items: flex-end;
  z-index: 999;
}

.modal-panel {
  width: 100%;
  max-height: 70vh;
  background: #fff;
  border-top-left-radius: 20rpx;
  border-top-right-radius: 20rpx;
  overflow: hidden;

  &.small {
    max-height: 60vh;
  }
}

.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 24rpx 28rpx;
  border-bottom: 1rpx solid #f0f0f0;

  text {
    font-size: 30rpx;
    font-weight: 600;
    color: #333;
  }

  .close {
    width: 60rpx;
    height: 60rpx;
    display: flex;
    align-items: center;
    border-radius: 50%;
    margin-right: 16rpx;
    flex-shrink: 0;
  }
}

/* 评论弹窗主体样式 */
.modal-body {
  max-height: 48vh;
  padding: 10rpx 20rpx 0;

  .cmt-item {
    display: flex;
    position: relative;
    padding: 18rpx 8rpx;
    border-bottom: 1rpx solid #f7f7f7;

    .cmt-avatar {
      width: 56rpx;
      height: 56rpx;
      border-radius: 50%;
      margin-right: 16rpx;
      flex-shrink: 0;
    }

    .cmt-main {
      flex: 1;

      .cmt-head {
        display: flex;
        align-items: center;
        justify-content: space-between;
        margin-bottom: 6rpx;

        .cmt-name { font-size: 26rpx; color: #333; font-weight: 600; }
        .cmt-time { font-size: 22rpx; color: #999; margin-left: 10rpx; }
      }

      .cmt-right { display: inline-flex; align-items: center; gap: 10rpx; }

      .cmt-text {
        display: block;
        font-size: 26rpx;
        color: #555;
        line-height: 1.6;
        margin-bottom: 8rpx;
      }

      .cmt-actions {
        display: flex;
        align-items: center;

        .act {
          display: inline-flex;
          align-items: center;
          margin-right: 24rpx;

          text { font-size: 22rpx; color: #888; margin-left: 6rpx; }
          text.liked { color: #ff6b6b; }
          text.collected { color: #f5a623; }
        }
      }
    }
  }
}

.empty {
  text-align: center;
  color: #999;
  padding: 40rpx 0;
  font-size: 26rpx;
}

.modal-input {
  display: flex;
  align-items: center;
  padding: 16rpx 20rpx calc(16rpx + env(safe-area-inset-bottom));
  border-top: 1rpx solid #f0f0f0;

  .modal-comment-input {
    flex: 1;
    height: 70rpx;
    background: #f7f7f7;
    border-radius: 35rpx;
    padding: 0 20rpx;
    font-size: 26rpx;
    margin-right: 16rpx;
  }

  .modal-send {
    padding: 14rpx 28rpx;
    background: #e0e0e0;
    border-radius: 20rpx;
    color: #999;
    font-size: 26rpx;

    &.active {
      background: #007aff;
      color: #fff;
    }
  }
}

/* 编辑弹窗内部样式 */
.edit-form {
  padding: 20rpx;

  .edit-title {
    width: 100%;
    height: 70rpx;
    background: #f7f7f7;
    border-radius: 12rpx;
    padding: 0 16rpx;
    font-size: 28rpx;
    margin-bottom: 16rpx;
  }

  .edit-content {
    width: 100%;
    min-height: 180rpx;
    background: #f7f7f7;
    border-radius: 12rpx;
    padding: 14rpx 16rpx;
    font-size: 28rpx;
  }
}

.edit-actions {
  display: flex;
  justify-content: flex-end;
  padding: 12rpx 20rpx 20rpx;

  .btn {
    padding: 14rpx 26rpx;
    border-radius: 12rpx;
    font-size: 26rpx;
    &.ghost { background: #f2f3f5; color: #666; }
    &.primary { background: #007aff; color: #fff; }
  }
}

/* 分享弹窗内部样式 */
.share-body {
  padding: 20rpx;

  .desc {
    font-size: 26rpx;
    color: #666;
    margin-bottom: 12rpx;
  }

  .share-link {
    width: 100%;
    min-height: 140rpx;
    background: #f7f7f7;
    border-radius: 12rpx;
    padding: 16rpx;
    font-size: 26rpx;
    color: #333;
  }
}

.share-actions {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16rpx;
  padding: 12rpx 20rpx 20rpx;

  .btn {
    flex: 1;
    text-align: center;
    padding: 16rpx 20rpx;
    background: #f2f3f5;
    border-radius: 12rpx;
    font-size: 26rpx;
    color: #333;

    &.ghost { background: #f2f3f5; color: #666; }
    &.primary { background: #007aff; color: #fff; }
  }
}

/* 采纳按钮通用样式 */
.adopt-wrap {
  display: inline-flex;
  align-items: center;
  padding: 4rpx 10rpx;
  border-radius: 999rpx;
  background: #eef5ff;
}
.adopt-wrap .adopt-text { color: #2d8cf0; font-size: 22rpx; margin-left: 4rpx; }
.adopt-wrap .adopted-text { color: #2ecc71; font-size: 22rpx; margin-left: 4rpx; }
.comment-right, .cmt-right { display: inline-flex; align-items: center; gap: 10rpx; }

/* 采纳禁用态 */
.adopt-wrap.disabled {
  opacity: .6;
  pointer-events: none;
}

/* 右上角固定采纳按钮/标记样式 */
.adopt-btn-fixed,
.adopt-badge-fixed {
  position: absolute;
  top: 20rpx;
  right: 20rpx;
  z-index: 2;
  padding: 8rpx 14rpx;
  border-radius: 999rpx;
  font-size: 22rpx;
  display: inline-flex;
  align-items: center;
  white-space: nowrap;
}
.adopt-btn-fixed {
  background: #e8f2ff;
  color: #2d8cf0;
  border: 1rpx solid #cfe0ff;
}
.adopt-btn-fixed.disabled { opacity: .6; pointer-events: none; }
.adopt-badge-fixed {
  background: #eafaf0;
  color: #2ecc71;
  border: 1rpx solid #c9f0d9;
}

/* 为固定采纳按钮预留右侧空间，避免与时间/操作重叠 */
.comments-list .comment-item { padding-right: 220rpx; }
.modal-body .cmt-item { padding-right: 220rpx; }
/* 头部行也做右侧让位，避免时间文字与右上角按钮重叠 */
.comments-list .comment-item .comment-header { padding-right: 220rpx; }
.modal-body .cmt-item .cmt-head { padding-right: 220rpx; }

.post-meta {
  font-size: 22rpx;
  color: #999;
  margin-bottom: 10rpx;
  .ended {
    color: #ff6b6b;
    margin-left: 10rpx;
  }
}

</style>